home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
C
/
LIB
/
UNIXLIB37B
/
!UnixLib37
/
src
/
unix
/
c
/
tty
< prev
next >
Wrap
Text File
|
1996-11-09
|
17KB
|
876 lines
/****************************************************************************
*
* $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/tty,v $
* $Date: 1996/11/06 22:01:42 $
* $Revision: 1.5 $
* $State: Rel $
* $Author: unixlib $
*
* $Log: tty,v $
* Revision 1.5 1996/11/06 22:01:42 unixlib
* Yet more changes by NB, PB and SC.
*
* Revision 1.4 1996/10/30 22:04:51 unixlib
* Massive changes made by Nick Burret and Peter Burwood.
*
* Revision 1.3 1996/07/21 22:12:31 unixlib
* CL_0001 Nick Burret
* Improve memory handling. Remove C++ library incompatibilities.
* Improve file stat routines.
*
* Revision 1.2 1996/05/06 09:01:35 unixlib
* Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
* Saved for 3.7a release.
*
* Revision 1.1 1996/04/19 21:35:27 simon
* Initial revision
*
***************************************************************************/
static const char rcs_id[] = "$Id: tty,v 1.5 1996/11/06 22:01:42 unixlib Rel $";
/* SYS V tty device driver for RiscOS */
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termio.h>
#include <sys/syslib.h>
#include <sys/types.h>
#include <sys/unix.h>
#include <sys/dev.h>
#include <sys/tty.h>
#include <sys/os.h>
#include <sys/param.h>
#include <sys/swis.h>
static struct tty *__t; /* current tty */
/* store the number of characters actually displayed for this single character
in the del buffer. When a backspace/delete is processed, then we know
how many characters to rub out. cx is a pointer to the current position
within the buffer and sx is the number of displayed characters on this line.
When a newline is written, cx and sx are reset to 0. */
#define __ttyx(x) /* increment cursor posn. by (x) */ \
(__t->sx += (x), \
__t->del[__t->cx = (__t->cx + 1) & (MAX_INPUT - 1)] = (x))
static int __ttyicanon (void *buf, int nbyte, struct file *f);
static int __ttyiraw (void *buf, int nbyte, struct file *f);
static int __ttyinput (int c, int iflag);
static void __ttyecho (int c, int oflag, int lflag);
static void __ttydel (int lflag);
static void __ttytab (int oflag);
static void __ttycr (int oflag);
static void __ttynl (int oflag);
static char __ttybaud[0x10] =
{0, 9, 1, 10, 11, 2, 0, 3, 12, 4, 13, 5, 6, 7, 8, 0};
/* get console window size */
static void
__tty_console_gwinsz (register struct winsize *w)
{
static int i[9] =
{132, 134, 135, 133, 128, 130, 129, 131, -1};
int o[8];
int r[10];
r[0] = (int) i;
r[1] = (int) o;
os_swi (OS_ReadVduVariables, r);
w->ws_col = o[1] - o[0] + 1;
w->ws_row = o[3] - o[2] + 1;
w->ws_xpixel = o[5] - o[4] + 1;
w->ws_ypixel = o[7] - o[6] + 1;
}
/* set console window size */
static void
__tty_console_swinsz (register struct winsize *w)
{
static int i[7] =
{132, 135, 128, 131, 4, 5, -1};
int o[6];
int r[10];
register int j;
r[0] = (int) i;
r[1] = (int) o;
os_swi (OS_ReadVduVariables, r);
os_vdu (28);
os_vdu (o[0]);
os_vdu (o[1] + w->ws_row - 1);
os_vdu (o[0] + w->ws_col - 1);
os_vdu (o[1]);
os_vdu (24);
j = o[2];
j <<= o[4];
os_vdu (j & 0xff);
os_vdu (j >> 8);
j = o[3] - (w->ws_ypixel - 1);
j <<= o[5];
os_vdu (j & 0xff);
os_vdu (j >> 8);
j = o[2] + w->ws_xpixel - 1;
j <<= o[4];
os_vdu (j & 0xff);
os_vdu (j >> 8);
j = o[3];
j <<= o[5];
os_vdu (j & 0xff);
os_vdu (j >> 8);
#ifdef SIGWINCH
/* Raise the 'Window size change' signal to notify any applications
that might be interested. */
raise (SIGWINCH);
#endif
}
/* read console */
static void
__tty_console_gterm (register struct termio *t)
{
int r[3];
os_byte (0xdc, 0, 0xff, r);
t->c_cc[VINTR] = r[1];
os_byte (0xe5, 0, 0xff, r);
if (r[1])
t->c_lflag &= ~ISIG;
else
t->c_lflag |= ISIG;
}
/* set console */
static void
__tty_console_sterm (register struct termio *t)
{
os_byte (0xdc, t->c_cc[VINTR], 0, 0);
if (t->c_lflag & ISIG)
os_byte (0xe5, 0, 0, 0);
else
os_byte (0xe5, 0xff, 0, 0);
}
/* set RS423 */
static void
__tty_423_sterm (register struct termio *t)
{
register int i, c;
int r[10];
i = t->c_cflag & CIBAUD;
i = i ? (i >> IBSHIFT) : (t->c_cflag & CBAUD);
r[0] = 5;
if (r[1] = __ttybaud[i])
os_swi (OS_SerialOp, r);
i = t->c_cflag & CBAUD;
r[0] = 6;
if (r[1] = __ttybaud[i])
os_swi (OS_SerialOp, r);
i = t->c_cflag;
switch (i & CSIZE)
{
case CS5:
c = 3;
break;
case CS6:
c = 2;
break;
case CS7:
c = 1;
break;
case CS8:
default:
c = 0;
break;
}
if (i & CSTOPB)
c |= 0x04;
if (i & PARENB)
{
c |= 0x08;
if (!(i & PARODD))
c |= 0x10;
}
r[0] = 1;
r[1] = c;
os_swi (OS_SerialOp, r);
}
int
__ttyopen (char *file, int mode, struct file *f)
{
struct tty *_t;
int l;
mode = mode;
switch (*(file + 5))
{
case 'c': /* console */
_t = __u->tty + (l = TTY_CON);
__u->status.tty_type = TTY_CON;
break;
case 'r': /* rs423 */
_t = __u->tty + (l = TTY_423);
__u->status.tty_type = TTY_423;
break;
case 't': /* tty */
_t = __u->tty + (l = __u->status.tty_type);
break;
default:
return (-1);
break;
}
{
register struct termio *t = _t->t;
t->c_iflag = BRKINT | ICRNL | IMAXBEL;
t->c_oflag = OPOST | ONLCR | XTABS;
if (l == TTY_CON)
t->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
else if (l == TTY_423)
t->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
t->c_lflag = ISIG | ICANON | ECHO;
t->c_line = 0;
{
static char cc[NCC] =
{CINTR, CQUIT, CERASE, CKILL, CEOF, CEOL, CEOL2,
CSWTCH, CSTART, CSTOP, CSUSP, 0, CREPRINT, CDISCARD, CWERASE, CLNEXT};
memcpy (t->c_cc, cc, NCC);
}
if (l == TTY_CON)
__tty_console_gterm (t); /* RS423 is set up later */
}
{
register struct winsize *w = _t->w;
if (l == TTY_CON)
__tty_console_gwinsz (w);
else if (l == TTY_423)
{
w->ws_col = 80;
w->ws_row = 25;
w->ws_xpixel = w->ws_ypixel = 0;
}
}
if (l == TTY_CON)
{
_t->out = os_vdu;
_t->in = os_get;
_t->scan = os_inkey;
_t->init = os_console;
_t->flush = os_keyflush;
}
else if (l == TTY_423)
{
_t->out = os_423vdu;
_t->in = os_423get;
_t->scan = os_423inkey;
_t->init = os_423;
_t->flush = os_423flush;
}
#ifndef __TTY_STATIC_BUFS
_t->buf = 0;
_t->del = 0;
#endif
_t->ptr = _t->buf;
_t->cnt = 0;
_t->sx = _t->cx = 0;
{
register int *r = f->r;
r[0] = r[1] = r[2] = r[3] = r[4] = 0;
r[5] = 0x33;
}
__funcall ((*(_t->init)), ());
if (l == TTY_423)
__tty_423_sterm (_t->t);
return (l);
}
int
__ttyclose (int l, struct file *f)
{
register struct tty *_t;
f = f;
_t = __u->tty + l;
#ifndef __TTY_STATIC_BUFS
if ((unsigned char*)_t->del >= __lomem && (unsigned char*)_t->del < __break)
free (_t->del);
if ((unsigned char*)_t->buf >= __lomem && (unsigned char*)_t->buf < __break)
free (_t->buf);
_t->buf = 0;
_t->del = 0;
#endif
_t->ptr = _t->buf;
_t->cnt = 0;
_t->sx = _t->cx = 0;
return (0);
}
int
__ttyread (int l, void *buf, int nbyte, struct file *f)
{
__t = __u->tty + l;
#ifndef __TTY_STATIC_BUFS
if (!__t->del)
{
if (!(__t->del = malloc (MAX_INPUT)))
{
errno = ENOMEM;
return (-1);
}
__t->sx = __t->cx = 0;
}
#endif
return ((__t->t->c_lflag & ICANON) ? \
__ttyicanon (buf, nbyte, f) : \
__ttyiraw (buf, nbyte, f));
}
static int
__ttyicanon (void *buf, register int nbyte, struct file *f)
{
register int c, i;
register char *s;
register int nflag;
register int iflag, oflag, lflag;
register char *cc;
int ceof, ceol, ceol2;
#define F_LNEXT 000001
#define F_MAX 000002
#define F_NDELAY 000004
#ifndef __TTY_STATIC_BUFS
if (!__t->buf)
{
if (!(__t->buf = malloc (MAX_INPUT)))
{
errno = ENOMEM;
return (-1);
}
__t->cnt = 0;
__t->ptr = __t->buf;
}
#endif
if (__t == __u->tty)
os_byte (0xe5, 0xff, 0, 0); /* disable SIGINT */
ret:
if (__t->cnt != 0)
{
if (__t == __u->tty)
os_byte (0xe5, 0, 0, 0); /* re-enable SIGINT */
i = (nbyte > __t->cnt) ? __t->cnt : nbyte;
memcpy (buf, __t->ptr, i);
__t->cnt -= i;
__t->ptr += i;
return (i);
}
nflag = (f->oflag & O_NDELAY) ? F_NDELAY : 0;
iflag = __t->t->c_iflag;
oflag = __t->t->c_oflag;
lflag = __t->t->c_lflag;
cc = (char *) __t->t->c_cc;
ceof = cc[VEOF];
if (!(ceol = cc[VEOL]))
ceol--;
if (!(ceol2 = cc[VEOL2]))
ceol2--;
s = __t->ptr = __t->buf;
__t->sx = __t->cx = 0;
i = 0;
for (;;)
{
if (i < MAX_INPUT)
nflag &= ~F_MAX;
else
nflag |= F_MAX;
if (nflag & F_NDELAY)
c = __funcall ((*(__t->scan)), (0));
else
c = __funcall ((*(__t->in)), ());
if (c < 0)
goto eol;
if (c == '\r' && iflag & IGNCR)
continue;
c = __ttyinput (c, iflag);
if (!(nflag & F_LNEXT))
{
if (c == '\n' || c == ceof || c == ceol || c == ceol2)
goto eol;
if (c == cc[VLNEXT])
{
nflag |= F_LNEXT;
continue;
}
if (c == cc[VERASE])
{
if (i)
{
__ttydel (lflag);
i--;
}
continue;
}
if (c == cc[VWERASE])
{
while (--i >= 0 && isspace (s[i]))
__ttydel (lflag);
i++;
while (--i >= 0 && !isspace (s[i]))
__ttydel (lflag);
i++;
continue;
}
if (c == cc[VKILL])
{
while (--i >= 0)
__ttydel (lflag);
i++;
if (lflag & ECHOK)
__ttynl (oflag);
continue;
}
if (c == cc[VREPRINT])
{
register int j;
__ttyecho (c, oflag, lflag);
__ttynl (oflag);
if (!(oflag & ONLRET))
__ttycr (oflag);
for (j = 0; j < i; j++)
__ttyecho (s[j], oflag, lflag);
continue;
}
if (lflag & ISIG)
{
if (c == cc[VINTR])
{
raise (SIGINT);
continue;
}
if (c == cc[VQUIT])
{
raise (SIGQUIT);
continue;
}
}
}
else
nflag &= ~F_LNEXT;
if (nflag & F_MAX)
{
if (iflag & IMAXBEL)
__funcall ((*(__t->out)), ('\007'));
}
else
{
__ttyecho (c, oflag, lflag);
s[i++] = c;
}
}
eol:
if (c != cc[VEOF] && c >= 0)
{
if (!(nflag & F_MAX))
{
__ttyecho (c, oflag, lflag);
s[i++] = c;
}
}
if (__t->cnt = i)
goto ret;
else
{
if (__t == __u->tty)
os_byte (0xe5, 0, 0, 0); /* re-enable SIGINT */
return (0);
}
#undef F_LNEXT
#undef F_MAX
#undef F_NDELAY
}
static int
__ttyiraw (void *buf, register int nbyte, struct file *f)
{
register int c, i;
register char *s;
register int nflag;
register int iflag, oflag, lflag;
register char *cc;
register unsigned int vm, vt;
#define F_NSCAN 000001
nflag = 0;
iflag = __t->t->c_iflag;
oflag = __t->t->c_oflag;
lflag = __t->t->c_lflag;
cc = (char *) __t->t->c_cc;
if (f->oflag & O_NDELAY)
vm = vt = 0;
else
{
vm = (cc[VMIN] && cc[VTIME]) ? 1 : cc[VMIN];
vt = cc[VTIME] * 10;
}
if (cc[VMIN] && !cc[VTIME])
nbyte = vm, nflag |= F_NSCAN;
s = buf;
i = 0;
while (i < nbyte)
{
if (nflag & F_NSCAN)
c = __funcall ((*(__t->in)), ());
else
c = __funcall ((*(__t->scan)), (vt));
if (c < 0)
{
if (i >= vm)
return (i);
else
continue;
}
if (c == '\r' && iflag & IGNCR)
continue;
c = __ttyinput (c, iflag);
if (lflag & ISIG)
{
if (c == cc[VINTR] && __t != __u->tty)
{
raise (SIGINT);
continue;
}
if (c == cc[VQUIT])
{
raise (SIGQUIT);
continue;
}
}
__ttyecho (c, oflag, lflag);
s[i++] = c;
}
return (i);
#undef F_NSCAN
}
int
__ttywrite (int l, void *buf, int nbyte, struct file *f)
{
register int i, c;
register char *s;
register int oflag, lflag;
register char *cc;
register int (*out) (int);
f = f;
__t = __u->tty + l;
#ifndef __TTY_STATIC_BUFS
if (!__t->del)
{
if (!(__t->del = malloc (MAX_INPUT)))
{
errno = ENOMEM;
return (-1);
}
__t->sx = __t->cx = 0;
}
#endif
oflag = __t->t->c_oflag;
lflag = __t->t->c_lflag;
cc = (char *) __t->t->c_cc;
out = __t->out;
s = buf;
i = 0;
while (i < nbyte)
{
c = s[i++];
if ((oflag & (OPOST | OLCUC)) == (OPOST | OLCUC))
if (isupper (c))
c = _tolower (c);
if (c == cc[VERASE])
__ttydel (lflag);
else if (c == '\t')
__ttytab (oflag);
else if (c == '\n')
__ttynl (oflag);
else if (c == '\r')
__ttycr (oflag);
else
{
__ttyx (1);
__funcall ((*out), (c));
}
}
return (nbyte);
}
static int
__ttyinput (register int c, register int iflag)
{
if (iflag & ISTRIP)
c &= 0x7f;
if (iflag & IUCLC)
if (isupper (c))
c += ('a' - 'A');
if (iflag & INLCR)
if (c == '\n')
c = '\r';
if (iflag & ICRNL)
if (c == '\r')
c = '\n';
return (c);
}
static void
__ttyecho (register int c, register int oflag, register int lflag)
{
if (!((lflag & ECHO) || ((c == '\n') && (lflag & ECHONL))))
return;
if (c == '\t')
__ttytab (oflag);
else if (c == '\n')
__ttynl (oflag);
else if (c == '\r')
__ttycr (oflag);
else if (iscntrl (c))
{
__ttyx (2);
__funcall ((*(__t->out)), ('^'));
__funcall ((*(__t->out)), ((c == 0x7f) ? '?' : (c + '@')));
}
else
{
__ttyx (1);
__funcall ((*(__t->out)), (c));
}
}
static void
__ttydel (register int lflag)
{
register int x;
#ifndef __TTY_STATIC_BUFS
/* this should be impossible since the call path to this static function
should have already checked __t->del. */
if (!__t->del)
{
if (!(__t->del = malloc (MAX_INPUT)))
{
errno = ENOMEM;
return;
}
__t->sx = __t->cx = 0;
}
#endif
if (__t->sx)
{
x = __t->del[__t->cx];
__t->cx = (__t->cx - 1) & (MAX_INPUT - 1);
}
else
x = 1;
__t->sx = (__t->sx > x) ? (__t->sx - x) : 0;
if (lflag & ECHO)
{
if (lflag & ECHOE)
while (x--)
{
__funcall ((*(__t->out)), ('\b'));
__funcall ((*(__t->out)), (' '));
__funcall ((*(__t->out)), ('\b'));
}
else
while (x--)
__funcall ((*(__t->out)), ('\177'));
}
}
static void
__ttytab (register int oflag)
{
if ((oflag & (OPOST | XTABS)) == (OPOST | XTABS))
{
register int x;
x = (8 - (__t->sx & 0x7));
__ttyx (x);
while (x--)
__funcall ((*(__t->out)), (' '));
}
else
{
__ttyx (1);
__funcall ((*(__t->out)), ('\t'));
}
}
static void
__ttycr (register int oflag)
{
__t->sx = 0;
if ((oflag & (OPOST | OCRNL)) == (OPOST | OCRNL))
__funcall ((*(__t->out)), ('\n'));
else if ((oflag & (OPOST | ONOCR)) != (OPOST | ONOCR))
__funcall ((*(__t->out)), ('\r'));
}
static void
__ttynl (register int oflag)
{
if (oflag & OPOST)
{
if (oflag & ONLCR)
if (__t->sx || !(oflag & ONOCR))
__funcall ((*(__t->out)), ('\r'));
if (oflag & (ONLCR | ONLRET))
__t->sx = 0;
}
__funcall ((*(__t->out)), ('\n'));
}
long
__ttylseek (int l, long lpos, int whence, struct file *f)
{
l = l;
lpos = lpos;
whence = whence;
f = f;
errno = ESPIPE;
return (-1);
}
int
__ttyioctl (int l, int request, void *arg, struct file *f)
{
register struct tty *_t = __u->tty + l;
f = f;
if (request == TIOCGWINSZ || request == TIOCSWINSZ)
{
register struct winsize *w = _t->w;
if (request == TIOCGWINSZ)
{
if (l == TTY_CON)
__tty_console_gwinsz (w);
memcpy (arg, w, sizeof (struct winsize));
}
else
{
memcpy (w, arg, sizeof (struct winsize));
if (l == TTY_CON)
__tty_console_swinsz (w);
}
}
else
{
register struct termio *t = _t->t;
if (request & TCDRAIN)
{
_t->ptr = _t->buf;
_t->cnt = 0;
__funcall ((*(_t->flush)), ());
}
switch (request & ~TCDRAIN)
{
case TCGETA:
if (l == TTY_CON)
__tty_console_gterm (t);
memcpy (arg, t, sizeof (struct termio));
break;
case TCSETA:
memcpy (t, arg, sizeof (struct termio));
if (l == TTY_CON)
__tty_console_sterm (t);
else if (l == TTY_423)
__tty_423_sterm (t);
break;
case TCSBRK:
if (l == TTY_423 && !arg)
os_423break (25);
break;
case 0:
break;
default:
errno = EINVAL;
return (-1);
break;
}
}
return (0);
}